package com.dalonedrow.engine.ui.base.panel;

import com.badlogic.gdx.Input.Buttons;
import com.dalonedrow.engine.systems.Time;
import com.dalonedrow.engine.systems.base.ProjectConstants;
import com.dalonedrow.engine.ui.base.GuiComponent;
import com.dalonedrow.engine.ui.base.GuiComponentImpl;
import com.dalonedrow.engine.ui.base.GuiComponentLibrary;
import com.dalonedrow.engine.ui.base.GuiSelectable;
import com.dalonedrow.engine.ui.base.GuiSelectableGroup;
import com.dalonedrow.engine.ui.base.GuiTextItem;
import com.dalonedrow.engine.ui.base.menu.MenuGroup;
import com.dalonedrow.engine.ui.impl.PanningMap;
import com.dalonedrow.globalvariables.constants.hq.GlobalConstants;

/**
 * @author Donald
 */
public abstract class Panel extends GuiComponentImpl {
	/**
	 * when the landscape alignment is chosen, items are displayed side-by-side,
	 * bottom-aligned.
	 */
	public static final int	LANDSCAPE_BOTTOM		= 2;
	/**
	 * when the landscape alignment is chosen, items are displayed side-by-side,
	 * center-aligned.
	 */
	public static final int	LANDSCAPE_CENTER		= 1;
	/**
	 * when the landscape alignment is chosen, items are displayed side-by-side,
	 * top-aligned.
	 */
	public static final int	LANDSCAPE_TOP			= 0;
	/** landscape. */
	public static final int	PAGELAYOUT_LANDSCAPE	= 0;
	/** portrait. */
	public static final int	PAGELAYOUT_PORTRAIT		= 1;
	/** center. */
	public static final int	PORTRAIT_CENTER			= 1;
	/** left. */
	public static final int	PORTRAIT_LEFT			= 0;
	/** right. */
	public static final int	PORTRAIT_RIGHT			= 2;
	/** flag indicating the panel should handle its own mouse over calls. */
	private boolean			handleMouseOverIndependent;
	/** the component's id. */
	private int				id;
	/** Default constructor. */
	public Panel() {
		id = GuiComponentLibrary.getInstance().getNextId();
	}
	/**
	 * Adds a child component.
	 * @param child the child {@link GuiComponent}
	 */
	public abstract void addChild(GuiComponent child);
	/**
	 * Adds a child component.
	 * @param name the name of the child
	 * @param child the child {@link GuiComponent}
	 */
	public abstract void addChild(String name, GuiComponent child);
	/** Clears all tooltip timers for any children. */
	public final void clearTooltipTimers() {
		for (int i = 0; i < getChildren().length; i++) {
			GuiComponent child = getChildren()[i];
			if (child instanceof Panel) {
				if (((Panel) child).hasTooltipText()
						&& ((Panel) child).hasTooltipText()
						&& ((Panel) child).hasTooltipTimerStarted()) {
					// treat panel as a tooltip item
					((Panel) child).stopTooltipTimer();
				} else {
					// look for children of panel
					((Panel) child).clearTooltipTimers();
				}
			} else if (child instanceof GuiSelectableGroup) {
				((GuiSelectableGroup) child).clearHighlight();
			} else if (child instanceof GuiSelectable) {
				((GuiSelectable) child).onHighlight(false);
				if (child instanceof GuiTextItem
						&& ((GuiTextItem) child).hasTooltipText()
						&& ((GuiTextItem) child).hasTooltipTimerStarted()) {
					((GuiTextItem) child).stopTooltipTimer();
				}
			} else if (child instanceof GuiTextItem
					&& ((GuiTextItem) child).hasTooltipText()
					&& ((GuiTextItem) child).hasTooltipTimerStarted()) {
				((GuiTextItem) child).stopTooltipTimer();
			}
		}
	}
	/**
	 * Gets the children.
	 * @return {@link GuiComponent}[]
	 */
	public abstract GuiComponent[] getChildren();
	/**
	 * {@inheritDoc}
	 */
	@Override
	public final int getId() {
		return id;
	}
	public boolean touchUp(final int screenX, final int screenY, 
			final int pointer, final int button) {
		for (int i = 0; i < getChildren().length; i++) {
			if (getChildren()[i] instanceof Panel) {
				((Panel) getChildren()[i]).touchUp(
						screenX, screenY, pointer, button);
			} else if (getChildren()[i] instanceof MenuGroup
					&& ((MenuGroup) getChildren()[i]).isInHotSpot(screenX, screenY)
					&& button == Buttons.LEFT) {
				int index = ((MenuGroup) getChildren()[i]).findItemIndex(screenX, screenY);
				GuiSelectable selected =
						((MenuGroup) getChildren()[i]).findItemByIndex(index);
				if (selected != null) {
					selected.onSelect();
				}
			} else if (getChildren()[i] instanceof GuiSelectable
					&& ((GuiSelectable) getChildren()[i]).isInHotSpot(screenX, screenY)
					&& button == Buttons.LEFT) {
				((GuiSelectable) getChildren()[i]).onSelect();
			} else if (getChildren()[i] instanceof PanningMap) {
				((PanningMap) getChildren()[i]).touchUp(screenX, screenY, pointer, button);
			}
		}
		return true;
	}
	/**
	 * Handles events that occur when the user hovers an item.
	 * @param x the x-coordinate
	 * @param y the y-coordinate
	 */
	public void handleMouseOver(final float x, final float y) {
		for (int i = 0; i < getChildren().length; i++) {
			GuiComponent child = getChildren()[i];
			if (child.isVisible()
					&& child.contains(x, y)) {
				// apply highlights and tooltips
				if (child instanceof Panel) {
					handlePanelMouseOver((Panel) child, x, y);
				} else if (child instanceof GuiSelectableGroup) {
					GuiSelectableGroup group = (GuiSelectableGroup) child;
					if (group.isInHotSpot(x, y)) {
						int index = group.findItemIndex(x, y);
						if (group.highlightIndex(index)) {
							ProjectConstants.getInstance().setCursor(
									GlobalConstants.CURSOR_12_HAND);
						}
					}
				} else if (child instanceof GuiSelectable) {
					if (((GuiSelectable) child).isInHotSpot(x, y)
							&& ((GuiSelectable) child).onHighlight(true)) {
						ProjectConstants.getInstance().setCursor(
								GlobalConstants.CURSOR_12_HAND);
					}
					if (child instanceof GuiTextItem) {
						GuiTextItem gti = (GuiTextItem) child;
						if (gti.hasTooltipText()) {
							if (gti.hasTooltipTimerStarted()) {
								// check to see if it's time
								// to display the tooltip
								long time = Time.getInstance().getGameTime();
								gti.updateTooltipTimer(time);
							} else { // start the tooltip timer
								long time = Time.getInstance().getGameTime();
								gti.startTooltipTimer(time);
							}
						}
					}
				} else if (child instanceof GuiTextItem) {
					GuiTextItem gti = (GuiTextItem) child;
					if (gti.hasTooltipText()) {
						if (gti.hasTooltipTimerStarted()) {
							// check to see if it's time
							// to display the tooltip
							gti.updateTooltipTimer(
									Time.getInstance().getGameTime());
						} else { // start the tooltip timer
							gti.startTooltipTimer(
									Time.getInstance().getGameTime());
						}
					}
				} else if (child instanceof PanningMap) {
					((PanningMap) child).handleMouseOver(x, y);
				}
			} else {
				// clear highlights and tooltips from
				// non-highlighted components
				if (child instanceof Panel) {
					Panel pnl = (Panel) child;
					if (pnl.hasTooltipText()
							&& pnl.hasTooltipTimerStarted()) {
						// panel has tooltip - stop them
						pnl.stopTooltipTimer();
					} else {
						// panel has no tooltip - stop children
						pnl.clearTooltipTimers();
					}
				} else if (child instanceof GuiTextItem
						&& ((GuiTextItem) child).hasTooltipText()
						&& ((GuiTextItem) child).hasTooltipTimerStarted()) {
					((GuiTextItem) child).stopTooltipTimer();
				} else if (child instanceof GuiSelectable) {
					((GuiSelectable) child).onHighlight(false);
				}
			}
		}
	}
	private void handlePanelMouseOver(final Panel pnl, final float x,
			final float y) {
		if (pnl.hasTooltipText()
				&& !pnl.isMouseOverHandledIndependent()) {
			// panel has a tooltip, children are ignored
			if (pnl.hasTooltipTimerStarted()) {
				// check to see if it's time
				// to display the tooltip
				pnl.updateTooltipTimer(
						Time.getInstance().getGameTime());
			} else { // start the tooltip timer
				pnl.startTooltipTimer(
						Time.getInstance().getGameTime());
			}
		} else {
			// panel has no tooltip, children are checked
			pnl.handleMouseOver(x, y);
		}
	}
	/**
	 * Gets the flag indicating the panel should handle its own mouse over
	 * calls.
	 * @return <code>boolean</code>
	 */
	protected final boolean isMouseOverHandledIndependent() {
		return handleMouseOverIndependent;
	}
	private void mouseOverGuiTextItem() {

	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void prepareForRendering() throws Exception {
		super.prepareForRendering();
		if (super.isVisible()
				&& super.getPosition() != null) {
			for (int i = 0; i < getChildren().length; i++) {
				getChildren()[i].prepareForRendering();
			}
		}
	}
	/**
	 * Sets the flag indicating the panel should handle its own mouse over
	 * calls.
	 * @param val if true, the panel handles its own mouse over calls; otherwise
	 *        the parent panel class handles them
	 */
	protected final void setHandleMouseOverIndependent(final boolean val) {
		handleMouseOverIndependent = val;
	}
}
